#include "test_task.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "systick.h"
#include "menu.h"
#include "oled.h"
#include "adc.h"
#include "HCSR501.h"
#include <stdio.h>
#include "dht11.h"
#include "usart.h"
#include "dma.h"
#include "string.h"
#include "light_strong.h"
#include "ld3320.h"
#include "ld3320fun.h"

//创建数据
Data data;

//缓冲区大小
#define BUF_SIZE 100
char buf[BUF_SIZE];

// 将数据整合到 buf 中的函数
void integrateDataToString(const Data* data, char* buf, int bufSize) {
    // 确保缓冲区足够大以存放所有数据和逗号以及 null 终止符
    if (bufSize <= 0) {
        return;
    }

    // 填充缓冲区为 null 终止符
    buf[bufSize - 1] = '\0';

    // 使用 snprintf 构建字符串，逗号作为分隔符
    snprintf(buf, bufSize, "%d,%d,%d\r\n", data->tem, data->hum, data->light_strong);
}


#define DEBOUNCE_DELAY_MS 80

uint16_t lastAdkeyValue = 0;
extern DHT11_Data_TypeDef DHT11_Data;//温湿度
extern uint8_t is_people;			 //人体红外
extern int adkey_value;					 //光照强度

extern uint32_t LED_R_state,LED_G_state,LED_B_state,Beep_state;//LED灯

//按键状态
typedef enum
{
	IDLE_STATE,   			//空闲
	PRESS_DETECTED_STATE,   //按键按下
	RELEASE_DETECTED_STATE, //按键释放
	SHORT_PRESS_STATE,      //短按
	LONG_PRESS_STATE,     	//长按
	DOUBLE_PRESS_STATE,     //双击
	LONG_PRESS_STATE_END    //长按结束状态
} ButtonState;

uint16_t SHORT_CLICK_THRESHOLD = 400;  // 这个是第一次松开时间和第二次按下时间的判断时长
uint16_t LONG_PRESS_THRESHOLD = 1000;   // 定义长按的时间阈值（以FreeRTOS时基为单位）
uint16_t PRESS_Time = 100;             // 判断毛刺时长
uint16_t BUTTON_ERROR_Time = 1500;   // 按键长久状态卡死阈值
ButtonState buttonState = IDLE_STATE;  //按键状态


#define NOTIFY_IDLE_STATE   (1 << 0)
#define NOTIFY_SHORT_PRESS  (1 << 1)
#define NOTIFY_LONG_PRESS   (1 << 2)
#define NOTIFY_DOUBLE_PRESS (1 << 3)
#define NOTIFY_ALL       (IDLE_STATE | NOTIFY_SHORT_PRESS | NOTIFY_LONG_PRESS | NOTIFY_DOUBLE_PRESS)

// 启动任务
#define START_TASK_PRIO 1
#define START_STK_SIZE  128 * 10
TaskHandle_t StartTask_Handler;
void start_task(void *arg);

//key 发送按键状态任务
#define KEY_SendNotifyTASK_PRIO 2
#define KEY_SendNotifySTK_SIZE 200
TaskHandle_t KEY_SendNotifyTask_Handle;
void key_SendNotifytask(void *arg);

//ShowMainWindow 任务
#define ShowWindow_RECVNotify_TASK_PRIO 2
#define ShowWindow_RECVNotify_STK_SIZE 200
TaskHandle_t ShowWindow_RECVNotifyTask_Handle;
void ShowWindow_RECVNotify_task(void *arg);

//DHT11 任务
#define DHT11_TASK_PRIO 3
#define DHT11_STK_SIZE 50
TaskHandle_t DHT11Task_Handle;
void DHT11_task(void *arg);

//人体红外 任务
#define HcRs501_TASK_PRIO 3
#define HcRs501_STK_SIZE 50
TaskHandle_t HcRs501Task_Handle;
void HcRs501_task(void *arg);

//LED 任务
#define LED_BEEP_TASK_PRIO 3
#define LED_BEEP_STK_SIZE 50
TaskHandle_t LED_BEEPTask_Handle;
void LED_BEEP_task(void *arg);

//USART 任务
#define USART_TASK_PRIO 2
#define USART_STK_SIZE 2000
TaskHandle_t USARTTask_Handle;
void USART_task(void *arg);

//显示菜单任务
void ShowWindow_RECVNotify_task(void *arg)
{
	while(1)
	{
		uint32_t notify_value = 0;
		//等待任务通知
		xTaskNotifyWait(NOTIFY_ALL,NOTIFY_ALL,&notify_value,portMAX_DELAY);
		if(notify_value & NOTIFY_IDLE_STATE)
		{
			OLED_Clear();
			OLED_RefreshGram();
			showMainWindow();
		}
		if(notify_value & NOTIFY_SHORT_PRESS)
		{
			OLED_Clear();
			OLED_RefreshGram();
			Show_OLED_BEEP();
		}
		if(notify_value & NOTIFY_LONG_PRESS)
		{
			OLED_Clear();
			OLED_RefreshGram();
			showMainWindow();
		}
		vTaskDelay (4000);
	}
}

// key 任务
void key_SendNotifytask(void *arg)
{	
	TickType_t pressStartTime = 0;        //记录按下时间
//	TickType_t lastReleaseTime = 0;       //记录上一次释放时间
	TickType_t ReleaseTime = 0;
	//接收通知的任务句柄通过参数传递
	TaskHandle_t recv_task_handler = arg;
	while (1)
	{
		int keyStatus = GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0);  //检测按键
		TickType_t currentTime = xTaskGetTickCount();
		switch (buttonState)
		{
		   case IDLE_STATE:		//空闲状态
			   xTaskNotify(recv_task_handler, NOTIFY_IDLE_STATE, eSetBits);
			   if (keyStatus == 0)   //如果按键按下
			   {
				  buttonState = PRESS_DETECTED_STATE; //切换到按键按下状态
				  pressStartTime = currentTime;       //记录按下时间
			   }
			   break;

		   case PRESS_DETECTED_STATE:    //按键 按下状态
			  if (keyStatus == 1)       //检测按键松开时间
			  {
				ReleaseTime = currentTime;  //记录按键放松时间
				buttonState = RELEASE_DETECTED_STATE;    //如果按下后释放则进入这里
			  }
			  else if (currentTime - pressStartTime > LONG_PRESS_THRESHOLD) //判断按键长按的时长如果符合则跳转到这里。
			  {
				buttonState = LONG_PRESS_STATE;
			  }
			  else if(currentTime - pressStartTime>BUTTON_ERROR_Time) //防止按键卡死
			  {
				buttonState = IDLE_STATE;
			  }
			  break;
			  
			case LONG_PRESS_STATE_END:    //长按结束后的状态跳转这里等待按键松开 防止一直处于长按状态   /
			  if (keyStatus == 1)
			  {
				buttonState = IDLE_STATE;
			  }
			  break;

			case RELEASE_DETECTED_STATE:    //按键释放过后的状态
			  if ( (keyStatus == 0) && (currentTime - ReleaseTime < SHORT_CLICK_THRESHOLD))        //如果按键再次按下并且第二次时长是在500ms以内按下的
			  {
				buttonState = DOUBLE_PRESS_STATE;
			  }
			  else if ( (ReleaseTime - pressStartTime > PRESS_Time) && (currentTime - ReleaseTime > SHORT_CLICK_THRESHOLD)) //判断按键按下时长防止毛刺 在判断当前是否在双击范围内
			  {
				buttonState = SHORT_PRESS_STATE;
			  }
			  else if (currentTime - ReleaseTime > BUTTON_ERROR_Time) //按键出现无法判断情况回到初态
			  {
				buttonState = IDLE_STATE;
			  }
			  break;

			case SHORT_PRESS_STATE:						//短按
			  buttonState = LONG_PRESS_STATE_END;
			  //xTaskNotify(recv_task_handler, NOTIFY_BEEP_ON, eSetBits);
			  xTaskNotify(recv_task_handler, NOTIFY_SHORT_PRESS, eSetBits);//传递通知短按
//			  vTaskSuspend(ShowWindow_RECVNotifyTask_Handle);//挂起主窗口任务
//			  OLED_Clear();
//			  Show_OLED_BEEP();				    //短按实现进入控制OLED页面
			  break;

			case LONG_PRESS_STATE:					//长按
			  buttonState = LONG_PRESS_STATE_END;
			  xTaskNotify(recv_task_handler, NOTIFY_LONG_PRESS, eSetBits);//传递通知长按
//			  vTaskResume(ShowWindow_RECVNotifyTask_Handle);
//			  vTaskSuspend();
//			  showMainWindow();
			  break;

			case DOUBLE_PRESS_STATE:				//双击
			  buttonState = LONG_PRESS_STATE_END;
			  xTaskNotify(recv_task_handler, NOTIFY_DOUBLE_PRESS, eSetBits);//传递通知双击
			  break;
			}
			vTaskDelay (10);
		}
}

//DHT11+光照任务
void DHT11_task(void *arg)
{
	while(1)
	{
		Read_DHT11(&DHT11_Data);
		data.tem = DHT11_Data.temp_int;
		data.hum = DHT11_Data.humi_int;
		
		//获取光照强度
		uint16_t adkey_value = adc1_ch10_get_adkey_value();
		data.light_strong = adkey_value;
		vTaskDelay (10);
	}
}

//人体红外任务
void HcRs501_task(void *arg)
{
	while(1)
	{
		is_people =  Gain_HcRs501();
		data.people = is_people;//获取人体数据
		vTaskDelay (10);
	}
}

//LED BEEP任务
void LED_BEEP_task(void *arg)
{
	while(1)
	{
		LED_R_state = get_LED_R_state();
		LED_G_state = get_LED_G_state();
		LED_B_state = get_LED_B_state();
		Beep_state = get_Beep_state();
		
		data.LED_R = LED_R_state;
		data.LED_G = LED_G_state;
		data.LED_B = LED_B_state;
		data.BEEP = Beep_state;
		
		vTaskDelay (10);
	}
}

//USART 任务
void USART_task(void *arg)
{
	int cmd;
	while (1)
	{
		integrateDataToString(&data,buf,BUF_SIZE);
		dma1_ch4_to_usart1_tx(buf,strlen(buf));
//		printf("%d,%d,%d\r",data.tem,data.hum,data.people);
		scanf("%d", &cmd);
		if (cmd == 0) 
		{
			LED_R_ON();
		} else if (cmd == 1) {
			LED_R_OFF();
		} else if (cmd == 2) {
			LED_G_ON();
		}
		else if (cmd == 3) 
		{
			LED_G_OFF();
		}else if (cmd == 4) {
			LED_B_ON();
		}
		else if (cmd == 5) 
		{
			LED_B_OFF();
		}else if (cmd == 6) {
			BEEP_ON();
		}
		else if (cmd == 7) 
		{
			BEEP_OFF();
		}
		else 
		{
			printf("CMD ERROR\r\n");
		}
		
		// 等待传输完成
		while (DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET);
		// 清除标志
		DMA_ClearFlag(DMA1_FLAG_TC4);
		vTaskDelay (1000);
	}
}


////创建 key 任务
//void create_key_task(void)
//{
//	xTaskCreate(key_SendNotifytask,"key press task",KEY_SendNotifySTK_SIZE,NULL,KEY_SendNotifyTASK_PRIO,&KEY_SendNotifyTask_Handle);
//}

////创建 主菜单 任务
//void create_ShowMainWindow_task(void)
//{
//	xTaskCreate(ShowWindow_RECVNotify_task,"ShowMainWindow task",ShowWindow_RECVNotify_STK_SIZE,NULL,ShowWindow_RECVNotify_TASK_PRIO,&ShowWindow_RECVNotifyTask_Handle);
//}

//创建 温湿度 任务
void create_DHT11_task(void)
{
	xTaskCreate(DHT11_task,"DHT11 task",DHT11_STK_SIZE,NULL,DHT11_TASK_PRIO,&DHT11Task_Handle);
}
//创建 人体红外 任务
void create_HcRs501_task(void)
{
	xTaskCreate(HcRs501_task,"HcRs501 task",HcRs501_STK_SIZE,NULL,HcRs501_TASK_PRIO,&HcRs501Task_Handle);
}

//创建 LED BEEP 任务
void create_LED_BEEP_task(void)
{
	xTaskCreate(LED_BEEP_task,"LED_BEEP press task",LED_BEEP_STK_SIZE,NULL,LED_BEEP_TASK_PRIO,&LED_BEEPTask_Handle);
}

//创建 USART 任务
void create_USART_task(void)
{
	xTaskCreate(USART_task,"USART task",USART_STK_SIZE,NULL,USART_TASK_PRIO,&USARTTask_Handle);
}

// 启动任务函数
void start_task(void *arg)
{
	// 进入临界区
	taskENTER_CRITICAL();
	
	create_Ld3320_task();
	//按键发送通知和showWindow接收任务
//	create_send_recv_notify_task();
	
	//创建USART任务
	//create_USART_task();
	
	
	
//	//创建KEY任务 优先级 3
//	create_key_task();
//	
//	//创建ShowMainWindow 任务 2
//	create_ShowMainWindow_task();
	//创建LED任务
//	create_LED_BEEP_task();
//	//创建DHT11任务 优先级4
//	create_DHT11_task();
//	
//	//创建人体红外任务 优先级4
//	create_HcRs501_task();
	
//	// 清空 OLED 显示屏
    //OLED_Clear();
	
	// 删除启动任务
	vTaskDelete(StartTask_Handler);
	//vTaskSuspend(StartTask_Handler);
	
		// 退出临界区
	taskEXIT_CRITICAL();
}

// 创建启动任务
void create_start_task(void)
{
	xTaskCreate(start_task, "start task", START_STK_SIZE, NULL, START_TASK_PRIO, &StartTask_Handler);
}


// 创建发送、接收通知的任务
void create_send_recv_notify_task(void)
{
	// 先创建接收通知的任务
	xTaskCreate(ShowWindow_RECVNotify_task, "recv task", ShowWindow_RECVNotify_STK_SIZE, NULL, ShowWindow_RECVNotify_TASK_PRIO, &ShowWindow_RECVNotifyTask_Handle);
	// 再创建发送通知的任务，传递接收通知的任务句柄
	xTaskCreate(key_SendNotifytask, "send task", KEY_SendNotifySTK_SIZE, ShowWindow_RECVNotifyTask_Handle, KEY_SendNotifyTASK_PRIO, &KEY_SendNotifyTask_Handle);
}
